#include "common.h"
#include "select.h"
#include "db_mysql.h"
#include "list.h"
#include "hash.h"
#include <time.h>

// 全局变量
extern List* g_pList;    // 顺序表(未发送数据的客户端)
extern Hash*g_pHash;    // 哈希表(已发送数据的设备)
int g_lastCheckTime = 0; // 上次检查时间

// 初始化网络
int Init() {
    int sfd;
    struct sockaddr_in svr_addr;
    int slen;
    int res;

    sfd =socket(AF_INET,SOCK_STREAM,0);
    if(sfd>=0)
    {
        printf("socket ok\n");
    }
    slen=sizeof(svr_addr);
    bzero(&svr_addr,slen);

    svr_addr.sin_family=AF_INET;
    svr_addr.sin_port=htons(8848);
    svr_addr.sin_addr.s_addr=INADDR_ANY;

    res=bind(sfd,(struct sockaddr*)&svr_addr,slen);
    if(res==0)
    {
        printf("bind ok\n");
    }

    listen(sfd,20);

    return sfd;
}

// 接受客户端连接
int AcceptFd(int iServer, fd_set* pSet) {
    struct sockaddr_in c_addr;
    int clen;

    clen=sizeof(c_addr);
    bzero(&c_addr,clen);

    int cfd;
    cfd=accept(iServer,(struct sockaddr*)&c_addr,&clen);
    if(cfd<0)
    {
        printf("accept err\n");
    }

    FD_SET(cfd,pSet);

    return cfd;
}

// 从集合中删除描述符
int DelFdFromSet(int i, int iMax, fd_set* pSet) {
    FD_CLR(i,pSet);//从集合中删除i描述符

    if(i==iMax)
    {
        int nmax=0;
        int j;
        for(j=iMax-1;j>=0;j--)
        {
            if(FD_ISSET(j,pSet))//判断j描述符是否在集合中
            {
                nmax==j;
                break;
            }
        }
        return nmax;
    }
    return iMax;

}

// 处理客户端数据
void ProcessClientData(int fd, char* buffer) {
    char* arr[20] = {NULL};
    int count = 0;

    // 拆分数据
    if (FillArgv(buffer, arr, &count) != SYS_OK || count < 5) {
        printf("数据格式错误\n");
        return;
    }

    // 检查是否为设备上报数据
    if (strcmp(arr[0], "REPORT") != 0) {
        printf("非设备上报数据\n");
        return;
    }

    // 获取设备ID
    char device_id[MAX_DEVICE_ID_LEN] = {0};
    snprintf(device_id, sizeof(device_id), "%s", arr[1]);

    // 在顺序表中查找该客户端
    int foundInList = 0;
    dev_fd searchKey = {.fd = fd};
    int listIndex = SearchItem(g_pList, searchKey);

    if (listIndex != SYS_ERROR) {
        // 从顺序表删除
        dev_fd removed;
        DeleteList(g_pList, &removed, listIndex);
        foundInList = 1;
    }

    // 准备设备信息
    UserInfo devInfo;
    devInfo.iFd = fd;
    strncpy(devInfo.strDevice, device_id, sizeof(devInfo.strDevice));
    devInfo.lTime = time(NULL);

    // 在哈希表中查找设备
    int oldFd;
    int status = FindDevice(g_pHash, &devInfo, &oldFd);

    if (status == SYS_ERROR) {
        // 新设备 - 插入哈希表
        InsertItem(g_pHash, &devInfo);
        printf("新设备注册: %s\n", device_id);
    } else if (status == SYS_DEVICE_REINSERT) {
        // 设备重新连接 - 更新哈希表
        UpdateItem(g_pHash, &devInfo);
        printf("设备重新连接: %s\n", device_id);
    } else {
        // 已有设备 - 更新时间
        UpdateItem(g_pHash, &devInfo);
    }

    // 更新设备记录
    UpdateDeviceRecord(device_id);

    // 保存传感器数据
    DHT11SaveData(count, arr);
}

// 检查超时设备
void CheckTimeoutDevices() {
    time_t current = time(NULL);

    // 每20秒检查一次
    if (current - g_lastCheckTime >= DEVICE_TIMEOUT) {
        printf("检查超时设备...\n");
        int deleted = ProcessTimeoutDevices(g_pHash);
        printf("删除 %d 个超时设备\n", deleted);
        g_lastCheckTime = current;

        // 显示当前设备状态
        printf("当前在线设备:\n");
        ShowHash(g_pHash);
    }
}

// 主客户端处理循环
void AcceptClient(int iServer) {
    fd_set read_fds;
    FD_ZERO(&read_fds);
    FD_SET(iServer, &read_fds);
    int max_fd = iServer;

    // 初始化数据结构
    g_pList = CreateList();
    g_pHash = CreateHash();
    g_lastCheckTime = time(NULL);

    // 初始化数据库
    InitMysql();

    while (1) {
        // 设置超时时间为1秒
        struct timeval tv = {.tv_sec = 1, .tv_usec = 0};
        fd_set temp_fds = read_fds;
        int ret = select(max_fd + 1, &temp_fds, NULL, NULL, &tv);

        // 定期检查超时设备
        CheckTimeoutDevices();

        if (ret < 0) {
            perror("select error");
            continue;
        }

        if (ret == 0) {
            continue; // 超时
        }

        // 检查新的客户端连接
        if (FD_ISSET(iServer, &temp_fds)) {
            int cfd = AcceptFd(iServer, &read_fds);
            if (cfd > max_fd) max_fd = cfd;

            // 添加到顺序表
            dev_fd newClient = {.fd = cfd, .lTime = time(NULL)};
            InsertList(g_pList, newClient, g_pList->iCount);
            printf("新客户端连接: fd=%d\n", cfd);
        }

        // 检查客户端数据
        for (int i = 0; i <= max_fd; i++) {
            if (i != iServer && FD_ISSET(i, &temp_fds)) {
                char buffer[BUF_SIZE] = {0};
                int len = recv(i, buffer, sizeof(buffer) - 1, 0);

                if (len <= 0) {
                    // 客户端断开连接
                    close(i);
                    FD_CLR(i, &read_fds);
                    max_fd = DelFdFromSet(i, max_fd, &read_fds);
                    printf("客户端断开: fd=%d\n", i);
                } else {
                    // 处理客户端数据
                    buffer[len] = '\0';
                    printf("接收数据[fd=%d]: %s\n", i, buffer);
                    ProcessClientData(i, buffer);
                }
            }
        }
    }

    // 清理资源
    DestroyList(g_pList);
    DestroyHash(g_pHash);
    CloseMysql();
}
